using System;
using System.Collections;
using System.Collections.Generic;
using Server;
using Server.Mobiles;
using Server.Items;
using Server.Multis;
using Server.Regions;
using Server.Spells;


namespace Server.Regions
{
	public class VendorRegion : GuardedRegion
	{
		private VendorManager m_Manager;

		public VendorManager Manager
		{
			get{ return m_Manager; }
		}

		public VendorRegion( VendorManager vm ) : base( vm.StringName, vm.Map, HouseRegion.HousePriority, vm.VendorArea )
		{
			m_Manager = vm;

			int music = Utility.Random( 67 );
			Music = (MusicName)music;
		}

		// TODO: to guard from recall and mark?
    public override bool AllowHousing( Mobile from, Point3D p )
    {
    	if ( m_Manager != null && !m_Manager.Deleted )
    	return m_Manager.AllowHousing;

			return false;
    }

		public override bool OnBeginSpellCast( Mobile m, ISpell s )
		{
			int spellID = SpellRegistry.GetRegistryNumber( s );

			bool restrictMark = false;
			bool restrictTeleport = false;
			bool restrictRecall = false;

			if ( m_Manager != null && !m_Manager.Deleted )
			{
				restrictMark = m_Manager.RestrictMark;
				restrictTeleport = m_Manager.RestrictTeleport;
				restrictRecall = m_Manager.RestrictRecall;
			}

//			m.SendMessage( "SpellID: {0}.", spellID );	// debug code

			if ( m.AccessLevel < AccessLevel.GameMaster && ( ( restrictMark && spellID == 44 ) 		// spell Mark
				|| ( restrictTeleport && spellID == 21 ) || ( restrictRecall && spellID == 31 ) ) )	// spell Teleport, Recall
			{
				m.SendLocalizedMessage( 501802 );		// Thy spell doth not appear to work...
				return false;
			}

			return base.OnBeginSpellCast( m, s );
		}

		public override void OnExit( Mobile m )
		{
			base.OnExit( m );

			if ( m != null && m is BaseCreature && m is IHardsellable )
			{
				BaseCreature bc = m as BaseCreature;
				BaseAI bai = bc.AIObject;

				if ( m_Manager != null && m_Manager.AreaHome != Point3D.Zero )
				{
					bai.DoMove( m.GetDirectionTo( m_Manager.AreaHome ) );
					bc.Home = m_Manager.AreaHome;
					bc.RangeHome = m_Manager.AreaRange;
				}
				else
					bai.DoMove( m.GetDirectionTo( bc.Home ) );
			}
		}

		public override void OnEnter( Mobile m )
		{
			if ( m != null && m is BaseCreature && m is IHardsellable 
				&& m_Manager != null && m_Manager.AreaHome != Point3D.Zero )
			{
				BaseCreature bc = m as BaseCreature;

				bc.Home = m_Manager.AreaHome;
				bc.RangeHome = m_Manager.AreaRange;
			}

			int music = Utility.Random( 67 );
			Music = (MusicName)music;

			base.OnEnter( m );
		}

		// Credit: Jeff of RunUO. To detect a player on region edge
		// no aaplication yet
		public static List<Mobile> GetPlayersOnEdge( Region region )
		{
			List<Mobile> regionMobiles = region.GetMobiles();
			List<Mobile> edgeMobiles = new List<Mobile>();

			for ( int i = 0; i < regionMobiles.Count; i++ )
			{
			  Mobile m = regionMobiles[i];
			  Rectangle3D[] areas = GetAreas( region, m );

				if ( IsOnEdge( areas, m ) )
					edgeMobiles.Add( m );
			}

			return edgeMobiles;
		}

		private static Rectangle3D[] GetAreas( Region region, Mobile m )
		{
			List<Rectangle3D> containedAreas = new List<Rectangle3D>();

			for ( int i = 0; i < region.Area.Length; i++ )
			{
				if ( region.Area[i].Contains( m.Location ) )
					containedAreas.Add( region.Area[i] );
			}

			return containedAreas.ToArray();
		}

		private static bool IsOnEdge( Rectangle3D[] onEdgeArray, Mobile m )
		{
			if ( onEdgeArray.Length == 0 )
			  return false;
		
			if ( onEdgeArray.Length == 1 )
			  return IsOnEdge( onEdgeArray[0], m );

		  bool onEdge = true;

		  for ( int i = 0; i < onEdgeArray.Length && onEdge; i++ )
		  {
		    Rectangle3D a = onEdgeArray[i];

		    for ( int j = 0 + i; j < onEdgeArray.Length && onEdge; j++ )
		    {
		      if( i == j )
		      	continue;

		      Rectangle3D b = onEdgeArray[j];

		      onEdge = IsOnEdge(a, m) && IsOnEdge(b, m) &&
		               ( ( a.Start.X == b.Start.X && a.Start.Y == b.Start.Y ) ||
		               ( a.Start.X == b.Start.X && a.End.Y == b.End.Y ) ||
		               ( a.End.X == b.End.X && a.Start.Y == b.Start.Y ) ||
		               ( a.End.X == b.End.X && a.End.Y == b.End.Y ) );
		    }
		  }

		  return onEdge;
		}

		private static bool IsOnEdge( Rectangle3D rect, Mobile m )
		{
		  return ( m.Location.X == rect.Start.X ||
		           m.Location.Y == rect.Start.Y ||
		           m.Location.X == rect.End.X ||
		           m.Location.Y == rect.End.Y );
		}

	}
}